
using System;
using System.Threading;
using System.Threading.Tasks;
using Common.Pool;
using Cysharp.Threading.Tasks;
using UnityEngine;
using static MiniAnimation.MiniAnimate;

namespace MiniAnimation
{
    public interface IMiniAnim
    {
        UniTask DoMiniTo<T>(Getter<T> getter, Setter<T> setter, Lerp<T> lerpMethod, T targetValue, float duration,
        MiniCurve miniCurve = MiniCurve.None);
    }
    public class MiniAnim : SequenceNode, IMiniAnim
    {
        //用于判断是否已经被使用
        public bool isUsed;
        MiniCurve miniCurve = MiniCurve.None;
        public MiniCurve MiniCurve => miniCurve;
        public event Action onCompleted;
        public MiniAnim() : base()
        {
            Cts = new CancellationTokenSource();
            tcs = new TaskCompletionSource<bool>();
        }
        /// <summary>
        /// 杀死动画
        /// </summary>
        /// <param name="complete">是否完成动画终态，并调用OnComPlete</param>
        public override async void Kill()
        {
            base.Kill();
            if (isUsed)
            {
                miniCurve = MiniCurve.None;
                await UniTask.Yield();
            }
        }
        public MiniAnim SetCurve(MiniCurve curve)
        {
            miniCurve = curve;
            return this;
        }
        public MiniAnim RegisterCompleted(Action action)
        {
            onCompleted += action;
            return this;
        }
        void Complete()
        {
            onCompleted?.Invoke();
        }
        public void InitTask()
        {
            Cts = new CancellationTokenSource();
            tcs = new TaskCompletionSource<bool>();
        }
        async UniTask IMiniAnim.DoMiniTo<T>(Getter<T> getter, Setter<T> setter, Lerp<T> lerpMethod, T targetValue, float duration,
         MiniCurve miniCurve = MiniCurve.None)
        {
            float timer = 0;
            MiniCurve miniCurveType = MiniCurve.None;
            try
            {
                await UniTask.WaitUntil(() => !isPause, cancellationToken: Cts.Token);
            }
            catch (System.Exception e)
            {
                return;
            }
            T originValue = getter();
            if (duration > 0)
            {
                while (timer <= duration)
                {
                    if (Cts.Token.IsCancellationRequested)
                    {
                        bool completeRes = false;
                        tcs?.TrySetResult(completeRes);
                        return;
                    }
                    if (miniCurve != MiniCurve.None)
                    {
                        miniCurveType = miniCurve;
                    }
                    else
                    {
                        miniCurveType = this.MiniCurve;
                    }
                    float per = (float)EaseCurve.Evalute(miniCurveType, timer / duration);
                    T res;
                    res = lerpMethod(originValue, targetValue, per);
                    setter(res);
                    timer += Time.deltaTime;
                    //如果暂停了就等待恢复
                    try
                    {
                        await UniTask.WaitUntil(() => !isPause, cancellationToken: Cts.Token);
                    }
                    catch (System.Exception)
                    {
                        return;
                    }
                    await UniTask.Yield();
                    if (Cts.Token.IsCancellationRequested)
                    {
                        return;
                    }
                }
            }
            setter(targetValue);
            tcs.TrySetResult(true);
            this.Complete();
            {
                return;
            }
        }
        protected override async UniTask OnExcute()
        {
            await Task;
        }
    }
}